package com.runfast.common.service;

import com.runfast.common.dao.IMapper;
import com.runfast.common.exception.BaseException;
import com.runfast.common.web.entity.ResultCode;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ReflectionUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;

/**
 * Created by Administrator on 2018/1/30.
 */

@Transactional
public abstract class BaseService<M, ID extends Serializable, Example> implements IService<M, ID, Example> {
    @Autowired
    protected IMapper<M, ID, Example> mapper;

    private static final String ID_FIELD = "id";

    @Autowired
    private Validator validator;

    @Override
    public Validator getValidator() {
        return validator;
    }

    public void validate(Object object, Class<?>... groups) throws BaseException {
        Set<ConstraintViolation<Object>> constraintViolationSet = validator.validate(object, groups);
        if (!constraintViolationSet.isEmpty()) {
            ConstraintViolation<Object> next = constraintViolationSet.iterator().next();
            throw new BaseException(ResultCode.PARAMETER_ERROR, next.getPropertyPath().toString() + ": " + next.getMessage());
        }
    }


    public int countByExample(Example example) {
        return mapper.countByExample(example);
    }

    public int countByExampleWithPageable(Example example, Pageable pageable) {
        return mapper.countByExampleWithPageable(example, pageable);
    }


    /*public int deleteByExample(Example example) {
        return mapper.deleteByExample(example);
    }

    public int deleteByPrimaryKey(ID id) {
        Validate.notNull(id);
        return mapper.deleteByPrimaryKey(id);

    }*/


    public int insert(M record) {
        Validate.notNull(record);
        return mapper.insert(record);
    }


    public int insertSelective(M record) {
        Validate.notNull(record);
        return mapper.insertSelective(record);
    }


    public List<M> selectByExample(Example example) {
        return mapper.selectByExample(example);
    }

    public List<M> selectByExampleWithBLOBs(Example example) {
        return mapper.selectByExampleWithBLOBs(example);
    }


    public List<M> selectByExampleWithPageable(Example example, Pageable pageable) {
        return mapper.selectByExampleWithPageable(example, pageable);
    }

    public List<M> selectByExampleWithBLOBsWithPageable(Example example, Pageable pageable) {
        return mapper.selectByExampleWithBLOBsWithPageable(example, pageable);
    }


    public M selectByPrimaryKey(ID id) {
        Validate.notNull(id);
        return mapper.selectByPrimaryKey(id);

    }


    public int updateByExampleSelective(M record, Example example) {
        Validate.notNull(record);

        return mapper.updateByExampleSelective(record, example);
    }


    public int updateByExample(M record, Example example) {
        Validate.notNull(record);
        return mapper.updateByExample(record, example);
    }

    private void assertUpdate(M record) {
        Validate.notNull(record);

        Field field = ReflectionUtils.findField(record.getClass(), ID_FIELD);
        field.setAccessible(true);
        Object id = ReflectionUtils.getField(field, record);
        Validate.notNull(id);
    }

    public int updateByPrimaryKeySelective(M record) {
        assertUpdate(record);
        return mapper.updateByPrimaryKeySelective(record);
    }


    public int updateByPrimaryKey(M record) {
        assertUpdate(record);
        return mapper.updateByPrimaryKey(record);
    }
}
